#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <assert.h>
#include <vector>

#define MAX(a, b) (a) >= (b) ? (a) : (b)

int main(int argc, char* argv[]) {

    // 基本参数
    char *filename_matrix = argv[1];
    char *filename_rhs = argv[2];
    char *filename_sol = argv[3];
    int n = atoi(argv[4]);  

    // 读取向量的临时变量
    double *x = new double[n];
    double *b = new double[n];

    // x
    FILE *fp = fopen(filename_sol, "r");  
    double ck_sum = 0.0;
    for(int i = 0; i < n; i++)
    {
        fscanf(fp, "%lf", &x[i]);
        ck_sum += x[i];
    }
    fclose(fp);

    // printf("[x load finish]\n");
    // printf("[x check sum = %.10e]\n", ck_sum);

    // b
    fp = fopen(filename_rhs, "r");    
    fscanf(fp, "Vec_s = [\n");
    ck_sum = 0.0;
    for(int i = 0; i < n; i++)
    {
        fscanf(fp, "%lf", &b[i]);
        ck_sum += b[i];
    }
    fclose(fp);

    // printf("[b load finish]\n");
    // printf("[b check sum = %.10e]\n", ck_sum);

    // matrix
    std::vector<int> row_idx;
    std::vector<int> col_idx;
    std::vector<double> vals;
    ck_sum = 0.0;
    fp = fopen(filename_matrix, "r");
    int rid, cid;
    double val;
    while (fscanf(fp, "%d %d %lf", &rid, &cid, &val) != EOF) {
        // 1-based index
        row_idx.push_back(rid - 1);
        col_idx.push_back(cid - 1);
        vals.push_back(val);
        ck_sum += val;
    }     
    fclose(fp);

    // 计算点积和残差
    double b_norm = 0.0, r_norm = 0.0;
    double *r = new double[n];
    for (int i = 0; i < n; i++) {
        r[i] = b[i];
        b_norm += b[i] * b[i];
    }
    b_norm = sqrt(b_norm);

    for (int i = 0; i < row_idx.size(); i++) {
        int rid = row_idx[i], cid = col_idx[i];
        double val = vals[i];
        r[rid] -= val * x[cid];   
    }
    for (int i = 0; i < n; i++) {
        r_norm += r[i] * r[i];
    }
    r_norm = sqrt(r_norm);

    printf("||b - Ax|| / ||b|| = %.10e\n", r_norm / b_norm);

    return 0;
}

